package com.mayfool.gitmanager.ui;

import javax.swing.table.AbstractTableModel;
import java.util.Arrays;
import java.util.List;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @author zhou.xu
 * @description: 通用表格数据模型
 * 支持任意类型的数据展示，通过函数式接口提取数据属性
 * 提供了灵活的列值提取器配置，可以自定义数据展示方式
 * @date 2025/3/11 9:06
 * @since JDK 1.8
 */
public class CommonTableModel<T> extends AbstractTableModel {

    private static final long serialVersionUID = 4344241473044579089L;

    /**
     * 数据列表
     */
    private final List<T> dataList;

    /**
     * 列名数组
     */
    private final String[] columnNames;

    /**
     * 列值提取器数组
     * 每个元素是一个函数，用于从数据对象中提取对应列的值
     */
    private final Function<T, Object>[] columnValueExtractor;

    /**
     * 构造函数
     * @param dataList 数据列表
     * @param columnNames 列名数组
     * @param columnValueExtractor 列值提取器数组
     */
    public CommonTableModel(List<T> dataList, String[] columnNames, Function<T, Object>[] columnValueExtractor) {
        this.dataList = dataList == null ? List.of() : dataList;
        this.columnNames = columnNames == null ? new String[0] : columnNames;
        this.columnValueExtractor = columnValueExtractor;
    }

    /**
     * 获取行数
     * @return 数据列表的大小
     */
    @Override
    public int getRowCount() {
        return dataList.size();
    }

    /**
     * 获取列数
     * @return 列名数组的长度
     */
    @Override
    public int getColumnCount() {
        return columnNames.length;
    }

    /**
     * 获取列名
     * @param column 列索引
     * @return 列名
     */
    @Override
    public String getColumnName(int column) {
        return column >= 0 && column < columnNames.length ? columnNames[column] : "";
    }

    /**
     * 获取指定单元格的值
     * 通过列值提取器从数据对象中获取对应列的值
     * @param rowIndex 行索引
     * @param columnIndex 列索引
     * @return 单元格的值，如果索引无效或提取器不存在则返回null
     */
    @Override
    public Object getValueAt(int rowIndex, int columnIndex) {
        if (rowIndex < 0 || rowIndex >= dataList.size()) {
            return null;
        }
        T data = dataList.get(rowIndex);
        if (columnValueExtractor != null && columnIndex < columnValueExtractor.length) {
            return columnValueExtractor[columnIndex].apply(data);
        }
        return null;
    }

    /**
     * 获取指定行的数据对象
     * @param row 行索引
     * @return 数据对象，如果索引越界则返回null
     */
    public T getData(int row) {
        return row < dataList.size() ? dataList.get(row) : null;
    }

    /**
     * 获取选中行的数据对象列表
     * @param selectedRows 选中的行索引数组
     * @return 选中的数据对象列表
     */
    public List<T> getSelectedList(int[] selectedRows)  {
        return Arrays.stream(selectedRows)
                .mapToObj(this::getData)
                .collect(Collectors.toList());
    }
}
